Fric-frac model binding Person 1 op 1
Home

Fric-frac model binding Person 1 op 1

Fric-frac model binding Person 1 op 1

In deze les leren we hoe je het model aanpast voor een property die een foreign-key is. Uitleg hierover vind je op Relationships (10/27/2016). Een praktisch voorbeeld: Saineshwar Bageri, Binding Dropdown List With Database In ASP.NET Core MVC, Dec 12 2016

Probleem

In de tabel Person zit er een kolom met een foreign-key, namelijk CountryId verwijst naar de Country tabel.

  1. In het model hebben we dus een lijst van alle landen nodig zodat we die in een keuzelijst in de view kunnen tonen.
  2. In de ReadingOne moeten we de Name van het land tonen en niet de Id.

Oplossing

  1. In de Person/ReadingOne view willen we de naam van het land tonen en niet de Id:
    1. We passen het model aan. We voegen een property toe om de info over het land bij te houden:
      using Microsoft.AspNetCore.Mvc;
      using System;
      using System.Collections.Generic;
      using System.ComponentModel.DataAnnotations;
      using System.ComponentModel.DataAnnotations.Schema;
      
      namespace FricFrac.Models.FricFrac
      {
          public partial class Person
          {
              public Person()
              {
              }
      
              [Required]
              [StringLength(50)]
              [FromForm(Name = "Person-FirstName")]
              public string FirstName { get; set; }
              [Required]
              [StringLength(120)]
              [FromForm(Name = "Person-LastName")]
              public string LastName { get; set; }
              [StringLength(255)]
              [FromForm(Name = "Person-Email")]
              public string Email { get; set; }
              [StringLength(255)]
              public string Password { get; set; }
              [StringLength(255)]
              [FromForm(Name = "Person-Address1")]
              public string Address1 { get; set; }
              [StringLength(255)]
              [FromForm(Name = "Person-Address2")]
              public string Address2 { get; set; }
              [StringLength(20)]
              [FromForm(Name = "Person-PostalCode")]
              public string PostalCode { get; set; }
              [StringLength(80)]
              [FromForm(Name = "Person-City")]
              public string City { get; set; }
              [Required]
              [Column(TypeName = "int(11)")]
              [FromForm(Name = "Person-CountryId")]
              public int? CountryId { get; set; }
              [StringLength(25)]
              [FromForm(Name = "Person-Phone1")]
              public string Phone1 { get; set; }
              [Column(TypeName = "datetime")]
              [FromForm(Name = "Person-Birthday")]
              public DateTime? Birthday { get; set; }
              [Column(TypeName = "int(11)")]
              [FromForm(Name = "Person-Rating")]
              public int? Rating { get; set; }
              [FromForm(Name = "Person-Id")]
              [Column(TypeName = "int(11)")]
              public int Id { get; set; }
      
              [ForeignKey("CountryId")]
              public Country Country { get; set; }
         }
      }
    2. De namen van de landen bevatten Latijnse karakters zoals é, è enz. Om die correct uit de database in te lezen moeten we het model van Country aanpassen. Daarvoor heb je de MySql.Data.EntityFrameworkCore.DataAnnotations namespace nodig (MySQL Configuring Character Sets and Collations in EF Core):
      using Microsoft.AspNetCore.Mvc;
      using MySql.Data.EntityFrameworkCore.DataAnnotations;
      using System.ComponentModel.DataAnnotations;
      using System.ComponentModel.DataAnnotations.Schema;
      
      namespace FricFrac.Models.FricFrac
      {
          public partial class Country
          {
              public Country()
              {
              }
      
              [Required]
              [StringLength(50)]
              [MySqlCharset("latin1")]
              [FromForm(Name = "Country-Name")]
              public string Name { get; set; }
              [Required]
              [StringLength(2)]
              [FromForm(Name = "Country-Code")]
              public string Code { get; set; }
              [Column(TypeName = "int(11)")]
              [FromForm(Name = "Country-Id")]
              public int Id { get; set; }
              [FromForm(Name = "Country-Desc")]
              [StringLength(256)]
              public string Desc { get; set; }
          }
      }
    3. In de ReadingOne methode van de PersonController zoeken we de gegevens van de persoon op lezen we de gegevens van het land in en geven het model door aan de view:
      [HttpGet]
      public IActionResult ReadingOne(int? id)
      {
          ViewBag.Message = "Lees een Persoon in de database";
          if (id == null)
          {
              return NotFound();
          }
      
          var person = dbContext.Person.SingleOrDefault(m => m.Id == id);
          if (person == null)
          {
              return NotFound();
          }
          person.Country = dbContext.Country.SingleOrDefault(m => m.Id == person.CountryId);
          return View(person);
      }
    4. In de ReadingOne view van Person passen vangen we het model op en tonen de gegevens van de persoon in de HTML:
      @model FricFrac.Models.FricFrac.Person
      @{
          Layout = "~/Views/Shared/MasterLayout.cshtml";
      }
      <div class="control-panel">
          <a href="/Home/Index" class="tile _14x1">
              <span class="icon-menu2"></span>
              <span class="screen-reader-text">Home</span>
          </a>
          <h1>Fric-frac</h1>
      </div>
      <form class="show-room entity" action="/Person/Index" method="post">
          <div class="detail">
              <div class="command-panel">
                  <h2 class="banner">Persoon</h2>
                  <a href="/Person/UpdatingOne/@Model.Id" class="tile">
                      <span class="icon-pencil"></span>
                      <span class="screen-reader-text">Updating One</span>
                  </a>
                  <a href="/Person/InsertingOne" class="tile">
                      <span class="icon-plus"></span>
                      <span class="screen-reader-text">Inserting One</span>
                  </a>
                  <a href="/Person/DeleteOne/@Model.Id" class="tile">
                      <span class="icon-remove"></span>
                      <span class="screen-reader-text">Delete One</span>
                  </a>
                  <a href="/Person/Cancel" class="tile">
                      <span class="icon-close"></span>
                      <span class="screen-reader-text">Annuleren</span>
                  </a>
              </div>
              <fieldset>
                  <div>
                      <label for="Person-FirstName">Voornaam</label>
                      <span>@Model.FirstName</span>
                  </div>
                  <div>
                      <label for="Person-LastName">Familienaam</label>
                      <span>@Model.LastName</span>
                  </div>
                  <div>
                      <label for="Person-Email">E-mail</label>
                      <span>@Model.Email</span>
                  </div>
                  <div>
                      <label for="Person-Address1">Adres 1</label>
                      <span>@Model.Address1</span>
                  </div>
                  <div>
                      <label for="Person-Address2">Adres 2</label>
                      <span>@Model.Address2</span>
                  </div>
                  <div>
                      <label for="Person-PostalCode">Postcode</label>
                      <span>@Model.PostalCode</span>
                  </div>
                  <div>
                      <label for="Person-City">Stad</label>
                      <span>@Model.City</span>
                  </div>
                  <div>
                      <label for="Person-Country">Land</label>
                      <span>@Model.Country.Name</span>
                  </div>
                  <div>
                      <label for="Person-Phone1">Telefoon</label>
                      <span>@Model.Phone1</span>
                  </div>
                  <div>
                      <label for="Person-Birthday">Geboortedatum</label>
                      <span>@Model.Birthday</span>
                  </div>
              </fieldset>
              <div class="feedback"></div>
          </div>
          <aside class="list">
              <table></table>
          </aside>
      </form>
  2. In de InsertingOne view willen we de lijst van de landen tonen in de naam van het opgegeven land in de keuzelijst tonen:
    1. In de InsertingOne methode van de PersonController lezen we landen in en geven die aan de view door met behulp van de Viewbag:
      public IActionResult InsertingOne()
      {
          ViewBag.Title = "Fric-frac Person Inserting One";
          ViewBag.Countries = dbContext.Country.ToList();
          return View();
      }
    2. We passen de Person/InsertingOne view aan en lezen de option elementen uit de Countries lijst:
      @{
          Layout = "~/Views/Shared/MasterLayout.cshtml";
      }
      <nav class="control-panel">
          <a href="/Home/Index" class="tile">
              <span class="icon-menu2"></span>
              <span class="screen-reader-text">Home</span>
          </a>
          <h1 class="banner">Fric-frac</h1>
      </nav>
      <form class="show-room entity" action="/Person/InsertOne" method="post">
          <div class="detail">
              <div class="command-panel">
                  <h2 class="banner">Persoon</h2>
                  <button type="submit" value="/Person/InsertOne" class="tile">
                      <span class="icon-disk"></span>
                      <span class="screen-reader-text">Insert One</span>
                  </button>
                  <a href="/Person/Cancel" class="tile">
                      <span class="icon-close"></span>
                      <span class="screen-reader-text">Annuleren</span>
                  </a>
              </div>
              <fieldset>
                  <div>
                      <label for="Person-FirstName">Voornaam</label>
                      <input id="Person-FirstName" name="Person-FirstName" type="text" value="" required />
                  </div>
                  <div>
                      <label for="Person-LastName">Familienaam</label>
                      <input id="Person-LastName" name="Person-LastName" type="text" value="" required />
                  </div>
                  <div>
                      <label for="Person-Email">E-mail</label>
                      <input id="Person-Email" name="Person-Email" type="email" value="" />
                  </div>
                  <div>
                      <label for="Person-Address1">Adres 1</label>
                      <input id="Person-Address1" name="Person-Address1" type="text" value="" />
                  </div>
                  <div>
                      <label for="Person-Address2">Adres 2</label>
                      <input id="Person-Address2" name="Person-Address2" type="text" value="" />
                  </div>
                  <div>
                      <label for="Person-PostalCode">Postcode</label>
                      <input id="Person-PostalCode" name="Person-PostalCode" type="text" value="" />
                  </div>
                 <div>
                      <label for="Person-City">Stad</label>
                      <input id="Person-City" name="Person-City" type="text" value="" />
                  </div>
                  <div>
                      <label for="Person-CountryId">Land</label>
                      <select id="Person-CountryId" name="Person-CountryId">
                      @foreach (var item in ViewBag.Countries)
                      {
                          <option value="@item.Id">@item.Name</option>
                      }
                      </select>
                  </div>
                  <div>
                      <label for="Person-Phone1">Telefoon</label>
                      <input id="Person-Phone1" name="Person-Phone1" type="text" value="" />
                  </div>
                  <div>
                      <label for="Person-Birthday">Geboortedatum</label>
                      <input id="Person-Birthday" name="Person-Birthday" type="date" value="" />
                  </div>
                  <div>
                      <label for="Person-Rating">Tevreden</label>
                      <input id="Person-Rating" name="Person-Rating" type="range" value="" />
                  </div>
              </fieldset>
              <div class="feedback"></div>
          </div>
          <aside class="list">
              <table></table>
          </aside>
      </form>
  3. Om de persoon in de tabel te kunnen inserten passen we de InsertOne methode in de PersonController aan:
    [HttpPost]
    public IActionResult InsertOne(Models.FricFrac.Person person)
    {
        ViewBag.Message = "Insert een persoon in de database";
        dbContext.Person.Add(person);
        dbContext.SaveChanges();
        return View("Index", dbContext.Person);
    }
  4. In de Person/UpdatingOne view moeten we de keuzelijst ook opvullen met de landen uit de Country tabel. Maar er komt iets extra bij: in het keuzeveld moet de naam van het opgegeven land komen te staan:
    1. We beginnen met de methode UpdatingOne van PersonController aan te passen. We zoeken de gegevens de te updaten persoon op en halen alle landen op:
      public IActionResult UpdatingOne(int? id)
      {
          ViewBag.Title = "Fric-frac Person Updating One";
          if (id == null)
          {
              return NotFound();
          }
          var person = dbContext.Person.SingleOrDefault(m => m.Id == id);
          if (person == null)
          {
              return NotFound();
          }
          person.Country = dbContext.Country.SingleOrDefault(m => m.Id == person.CountryId);
          ViewBag.Countries = dbContext.Country.ToList();
          return View(person);
      }
    2. We passen vervolgens de UpdatingOne view aan. Let erop hoe we de geboortedatum formatteren:
      @model FricFrac.Models.FricFrac.Person
      @{
          Layout = "~/Views/Shared/MasterLayout.cshtml";
      }
      <nav class="control-panel">
          <a href="/Home/Index" class="tile">
              <span class="icon-menu2"></span>
              <span class="screen-reader-text">Home</span>
          </a>
          <h1>Fric-frac</h1>
      </nav>
      <form class="show-room entity" action="/Person/UpdateOne" method="post">
          <div class="detail">
              <div class="command-panel">
                  <h2 class="banner">Persoon</h2>
                 <button type="submit" class="tile">
                      <span class="icon-disk"></span>
                      <span class="screen-reader-text">Update One</span>
                  </button>
                 <a href="/Person/Cancel" class="tile">
                      <span class="icon-close"></span>
                      <span class="screen-reader-text">Annuleren</span>
                  </a>
              </div>
              <fieldset>
                  <input type="hidden" id="Person-Id" name="Person-Id" value="@Model.Id" />
      
                  <div>
                      <label for="Person-FirstName">Voornaam</label>
                      <input id="Person-FirstName" name="Person-FirstName" type="text" value="@Model.FirstName" required />
                  </div>
                  <div>
                      <label for="Person-LastName">Familienaam</label>
                      <input id="Person-LastName" name="Person-LastName" type="text" value="@Model.LastName" required />
                  </div>
                  <div>
                      <label for="Person-Email">E-mail</label>
                      <input id="Person-Email" name="Person-Email" type="email" value="@Model.Email" />
                  </div>
                  <div>
                      <label for="Person-Address1">Adres 1</label>
                      <input id="Person-Address1" name="Person-Address1" type="text" value="@Model.Address1" />
                  </div>
                  <div>
                      <label for="Person-Address2">Adres 2</label>
                      <input id="Person-Address2" name="Person-Address2" type="text" value="@Model.Address2" />
                  </div>
                  <div>
                      <label for="Person-PostalCode">Postcode</label>
                      <input id="Person-PostalCode" name="Person-PostalCode" type="text" value="@Model.PostalCode" />
                  </div>
                  <div>
                      <label for="Person-City">Stad</label>
                      <input id="Person-City" name="Person-City" type="text" value="@Model.City" />
                  </div>
                  <div>
                      <label for="Person-CountryId">Land</label>
                      <select id="Person-CountryId" name="Person-CountryId">
                          @foreach (var item in ViewBag.Countries)
                          {
                            <option value="@item.Id"
                                selected="@(item.Id == Model.CountryId ? true : false)">
                                @item.Name
                            </option>
                          }
                      </select>
                  </div>
                  <div>
                      <label for="Person-Phone1">Telefoon</label>
                      <input id="Person-Phone1" name="Person-Phone1" type="text" value="@Model.Phone1" />
                  </div>
                  <div>
                      <label for="Person-Birthday">Geboortedatum</label>
                      <input id="Person-Birthday" name="Person-Birthday" type="date"
                             value="@Model.Birthday.Value.ToString("yyyy-MM-dd")" />
                  </div>
              </fieldset>
              <div class="feedback"></div>
          </div>
          <aside class="list">
              <table></table>
          </aside>
      </form>
  5. We passen de UpdateOne methode in de PersonController aan om de wijzigingen naar de tabel weg te schrijven:
    [HttpPost]
    public IActionResult UpdateOne(Models.FricFrac.Person person)
    {
        if (ModelState.IsValid)
        {
            try
            {
                dbContext.Update(person);
                dbContext.SaveChanges();
                return RedirectToAction("Index");
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!dbContext.Person.Any(e => e.Id == person.Id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }
        }
        return View("Index", dbContext.Person);
    }
  6. De Cancel methode van de PersonController:
    public IActionResult Cancel()
    {
        return RedirectToAction("Index");
    }
  7. En tenslotte voegen we voor de volledigheid nog de DeleteOne methode toe in de PersonController:
    public IActionResult DeleteOne(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }
        var person = dbContext.Person.SingleOrDefault(m => m.Id == id);
        if (person == null)
        {
            return NotFound();
        }
        dbContext.Person.Remove(person);
        dbContext.SaveChanges();
        // keer terug naar de index pagina
        return RedirectToAction("Index");
    }

JI
2018-01-28 15:16:11